package com.tetris;

import com.common.GameBoard;

import java.awt.BorderLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowFocusListener;

import javax.swing.BorderFactory;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JToolBar;

// 主窗口
@SuppressWarnings("serial")
class MainWindow extends JFrame implements Game.Callback, ActionListener, KeyListener, WindowFocusListener {
    private final JButton mButtonMusic;         // "音乐"按钮
    private final JButton mButtonPause;         // "暂停"按钮
    private final Icon mButtonPauseImage;       // "暂停"按钮图片
    private final Icon mButtonPlayMusicImage;   // "播放音乐"按钮图片
    private final Icon mButtonResumeImage;      // "继续"按钮图片
    private final JButton mButtonStart;         // "开始"按钮
    private final Icon mButtonStopMusicImage;   // "停止音乐"按钮图片
    private Game mGame;                         // 游戏
    private final JLabel mLabelDifficulty;      // 难度值标签
    private final JLabel mLabelScore;           // 得分值标签

    /**
     * 构造方法。
     */
    public MainWindow() {
        // 设置当单击右上角的 X 按钮时退出程序
        super.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
        // 设置窗口标题
        super.setTitle(Const.getString("IDS_APP_NAME"));

        // 设置窗口尺寸不能改变
        super.setResizable(false);

        // 设置窗口尺寸
        super.setSize(Const.WIDTH, Const.HEIGHT);

        // 设置窗口居中
        super.setLocationRelativeTo(null);

        // 监听键盘事件
        super.addKeyListener(this);

        // 监听窗口焦点事件
        super.addWindowFocusListener(this);
        
        // 创建控件面板
        final JPanel panel = new JPanel();
        panel.setBounds(0, 0, Const.WIDTH, Const.HEIGHT);
        panel.setLayout(null);
        panel.setBackground(null);
        panel.setOpaque(false);
        super.add(panel);
        
        // 创建"操作说明"标签
        final JLabel labelHelp = new JLabel(Const.getString("IDS_HELP_TEXT"));
        labelHelp.setBounds(Const.LABEL_HELP_BOUNDS);
        labelHelp.setBorder(BorderFactory.createEtchedBorder());
        panel.add(labelHelp);
        
        // 设置"开始"按钮
        mButtonStart = new JButton();
        final ImageIcon buttonStartImage = new ImageIcon(Const.BUTTON_START_IMAGE_PATH);
        mButtonStart.setBounds(Const.BUTTON_START_POS.x, Const.BUTTON_START_POS.y, 
            buttonStartImage.getIconWidth(), buttonStartImage.getIconHeight());
        mButtonStart.addActionListener(this);
        mButtonStart.setIcon(buttonStartImage);
        panel.add(mButtonStart);

        // 设置"暂停"按钮
        mButtonPause = new JButton();
        mButtonPauseImage = new ImageIcon(Const.BUTTON_PAUSE_IMAGE_PATH);
        mButtonResumeImage = new ImageIcon(Const.BUTTON_RESUME_IMAGE_PATH);
        mButtonPause.setBounds(Const.BUTTON_PAUSE_POS.x, Const.BUTTON_PAUSE_POS.y, 
            mButtonPauseImage.getIconWidth(), mButtonPauseImage.getIconHeight());
        mButtonPause.addActionListener(this);
        mButtonPause.setEnabled(false);
        mButtonPause.setIcon(mButtonPauseImage);
        panel.add(mButtonPause);

        // 设置"音乐"按钮
        mButtonMusic = new JButton();
        mButtonPlayMusicImage = new ImageIcon(Const.BUTTON_MUSIC_PLAY_IMAGE_PATH);
        mButtonStopMusicImage = new ImageIcon(Const.BUTTON_MUSIC_STOP_IMAGE_PATH);
        mButtonMusic.setBounds(Const.BUTTON_MUSIC_POS.x, Const.BUTTON_MUSIC_POS.y, 
            mButtonPlayMusicImage.getIconWidth(), mButtonPlayMusicImage.getIconHeight());
        mButtonMusic.addActionListener(this);
        panel.add(mButtonMusic);
        mButtonMusic.setIcon(mButtonPlayMusicImage);
        
        // 创建状态栏
        final GridBagLayout layout = new GridBagLayout();
        final JToolBar statusBar = new JToolBar();
        statusBar.setLayout(layout);
        statusBar.setFloatable(false);

        final GridBagConstraints gbc = new GridBagConstraints();
        gbc.fill = GridBagConstraints.HORIZONTAL;
        gbc.weightx = 1;

        // 设置"难度"标签
        mLabelDifficulty = new JLabel();
        mLabelDifficulty.setBorder(BorderFactory.createEtchedBorder());
        mLabelDifficulty.setText(Const.getString("IDS_DIFFICULTY"));
        layout.setConstraints(mLabelDifficulty, gbc);
        statusBar.add(mLabelDifficulty);

        // 设置"得分"标签
        mLabelScore = new JLabel();
        mLabelScore.setBorder(BorderFactory.createEtchedBorder());
        mLabelScore.setText(Const.getString("IDS_SCORE"));
        layout.setConstraints(mLabelScore, gbc);
        statusBar.add(mLabelScore);
        
        // 添加状态栏
        super.add(statusBar, BorderLayout.SOUTH);
        
        // 设置主窗口背景
        final Icon image = new ImageIcon(Const.IMAGE_PATH);
        final JLabel labelBackground = new JLabel(image);
        labelBackground.setBounds(0, 0, image.getIconWidth(), image.getIconHeight());
        super.add(labelBackground);
        
        // 创建游戏区域
        final GameBoard gameBoard = new GameBoard(panel, Const.GAME_BOARD_X, Const.GAME_BOARD_Y, Const.GAME_BOARD_WIDTH, Const.GAME_BOARD_HEIGHT);

        // 创建预览区域
        final GameBoard preview = new GameBoard(panel, Const.PREVIEW_X, Const.PREVIEW_Y, Const.PREVIEW_WIDTH, Const.PREVIEW_HEIGHT);

        // 创建游戏
        mGame = new Game(this, gameBoard, gameBoard.getDrawer(), preview, preview.getDrawer());
    }

    /**
     * 所有按钮的单击响应方法。
     * @param e 事件相关信息
     */
    @Override
    public void actionPerformed(ActionEvent e) {
        final Object source = e.getSource();
        if (source == mButtonStart) {
            this.onButtonStartClicked();
        } else if (source == mButtonPause) {
            this.onButtonPauseClicked();
        } else if (source == mButtonMusic) {
            this.onButtonMusicClicked();
        }
        
        // 按完按钮后，让焦点回到窗口，否则不能响应键盘事件
        super.requestFocus();
    }

    /**
     * 按键事件的响应方法。
     * @param e 事件相关信息
     */    
    @Override
    public void keyPressed(KeyEvent e) {
        mGame.onKeyPressed(e.getKeyCode());
    }

    @Override
    public void keyReleased(KeyEvent e) {
    }

    @Override
    public void keyTyped(KeyEvent e) {
    }

    /**
     * "播放音乐"按钮的单击响应方法。
     */
    private void onButtonMusicClicked() {
        final boolean playingMusic = mGame.playMusic();
        if (playingMusic) {
            mButtonMusic.setIcon(mButtonStopMusicImage);
        } else {
            mButtonMusic.setIcon(mButtonPlayMusicImage);
        }
    }

    /**
     * "暂停"按钮的单击响应方法。
     */
    private void onButtonPauseClicked() {
        mGame.pause();
        final Game.Status status = mGame.getStatus();
        if (status == Game.Status.PAUSED) {
            mButtonPause.setIcon(mButtonResumeImage);
        } else if (status == Game.Status.PLAYING) {
            mButtonPause.setIcon(mButtonPauseImage);
        }
    }

    /**
     * "开始"按钮的单击响应方法。
     */
    private void onButtonStartClicked() {
        // 游戏开始
        mGame.start();
        
        // 设置按钮状态
        mButtonPause.setEnabled(true);
                
        // 设置按钮图片
        mButtonPause.setIcon(mButtonPauseImage);

        // 设置状态栏文字
        this.onDifficultyUp(1);
        this.onScore(0);
    }

    /**
     * 难度增加事件的响应方法。
     * @param difficulty    难度
    */
    @Override    
    public void onDifficultyUp(int difficulty) {
        mLabelDifficulty.setText(Const.getString("IDS_DIFFICULTY") + difficulty);
    }

    /**
     * 游戏结束事件的响应方法。
     * @param isWon  胜利则为 true，否则为 false
     */
    @Override    
    public void onGameOver(boolean isWon) {
        if (isWon) {
            JOptionPane.showMessageDialog(this, Const.getString("IDS_WON"), " ", JOptionPane.INFORMATION_MESSAGE);
        } else {
            JOptionPane.showMessageDialog(this, Const.getString("IDS_LOST"), " ", JOptionPane.INFORMATION_MESSAGE);
        }
        mButtonPause.setEnabled(false);
    }
    
    /**
     * 得分事件的响应方法。
     * @param score 得分
     */
    @Override
    public void onScore(int score) {
        mLabelScore.setText(Const.getString("IDS_SCORE") + score);
    }

    @Override
    public void windowGainedFocus(WindowEvent e) {
    }

    /**
     * 窗口失去焦点事件的响应方法。
     * @param e 事件相关信息
     */
    @Override
    public void windowLostFocus(WindowEvent e) {
        final Game.Status status = mGame.getStatus();
        if (status == Game.Status.PLAYING) {
            this.onButtonPauseClicked();
            mButtonPause.setIcon(mButtonResumeImage);
        }
    }
}
